package com.example.qihuibao.base

import android.app.Activity
import android.content.*
import android.net.ConnectivityManager
import android.os.Bundle
import android.os.IBinder
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import com.example.qihuibao.bean.*
import com.example.qihuibao.constant.Config
import com.example.qihuibao.constant.Global
import com.example.qihuibao.module.main.MainActivity
import com.example.qihuibao.module.service.SocketService
import com.example.qihuibao.module.service.NetworkStatusService
import com.example.qihuibao.module.service.SerialPortService
import com.example.qihuibao.module.service.TimerService
import com.example.qihuibao.network.RetrofitManager
import com.example.qihuibao.utils.*
import com.example.qihuibao.utils.extension.toast
import com.example.qihuibao.widget.dialog.LoadingDialog
import com.example.qihuibao.widget.dialog.ProgressDialog
import com.google.gson.Gson
import com.gyf.immersionbar.ImmersionBar
import com.koushikdutta.async.http.WebSocket
import com.maning.updatelibrary.InstallUtils
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import kotlin.system.exitProcess


/**
 *@author: cww
 *@desc: activity的基类 (尽量不要在基类添加一些额外的方法例如getLayoutId()，这样并不利于新手，也感觉奇怪)
 * 从整体来看，基类的设计必须是一个abstract class，并且提供必要的钩子函数给子类定制以及提供公共的常用的函数
 * 在基类的生命周期函数里面可以做一些统一的操作，一般来说是页面的打点
 * 对于Activity而言，有一些页面可能需要右滑返回功能，我们直接让BaseActivity继承SwipeBackActivity
 *@date: 4/17/23 10:05 PM
 */
abstract class BaseActivity<T : ViewBinding>(val inflater: (inflater: LayoutInflater) -> T) : AppCompatActivity(), ScannerKeyEventHelper.OnScanSuccessListener {
    companion object {
        fun start(srcActivity: Activity, dstActivityCls:Class<out AppCompatActivity>) {
            val intent = Intent(srcActivity, dstActivityCls)
            srcActivity.startActivity(intent)
            if (dstActivityCls == MainActivity::class.java) {
                srcActivity.finish()
            }
        }
        //串口二维码有关
        private var serialPortServiceConnection: ServiceConnection? = null
        private var qrCodeBack:((code:String)->Unit)? = null
        //本地服务站
        private var socketServiceConnection: ServiceConnection? = null
        var socketService: SocketService? = null
        private var stationBack:((data:String)->Unit)? = null
        //timer
        private var timerServiceConnection:ServiceConnection? = null
        private var timerBack:(()->Unit)? = null
        //network status
        private var networkServiceConnection: ServiceConnection? = null
        private val networkReceiver = object: BroadcastReceiver(){
            private var connectivityManager: ConnectivityManager? = null
            override fun onReceive(context: Context, intent: Intent?) {
                connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
                val networkInfo = connectivityManager?.activeNetworkInfo;
                Global.networkOk = networkInfo != null && networkInfo.isAvailable
            }
        }
        private var mScannerKeyEventHelper: ScannerKeyEventHelper? = null
        private var keyboardId = 0//区别于同时外接usb键盘和usb扫码枪
        private var scanBoxId = 0
    }

    protected lateinit var viewBinding: T
    private var loadingDialog: LoadingDialog? = null
    private var progressDialog: ProgressDialog? = null
    private var connectStationCountdown = Global._5S
    private var scanKeyInterval = 0L


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE
//                or View.SYSTEM_UI_FLAG_FULLSCREEN
//                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
//                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
//                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
//                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
//                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
//                or View.SYSTEM_UI_FLAG_IMMERSIVE)
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)// 隐藏状态栏
//        RxDevicesTool.navigation(this, false)
        viewBinding = inflater(layoutInflater)
        setContentView(viewBinding.root)

        if (enableImmersionBar()) {
            ImmersionBar.with(this)
                .statusBarColor(statusBarColor())//设置状态栏颜色，不设为透明
                .fitsSystemWindows(true)  //使得activity布局不要顶上状态栏
                .init();
        }

        if (this is MainActivity) {
            startSerialPortService()
            startNetworkService()
            startSocketService()
            startTimerService()
            registerReceiver(networkReceiver, IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"))
        }
    }

    override fun onStart() {
        super.onStart()
        //这里可以添加页面打点
    }

    override fun onPause() {
        super.onPause()
        qrCodeBack = null//保证当前activity才能获得串口二维码
        timerBack = null
        stationBack = null
    }

    override fun onStop() {
        super.onStop()
        //这里可以添加页面打点
    }

    override fun onDestroy() {
        super.onDestroy()
        if (this is MainActivity) {
            if (serialPortServiceConnection != null) {
                unbindService(serialPortServiceConnection!!)
            }
            if (socketServiceConnection != null) {
                unbindService(socketServiceConnection!!)
            }
            if (timerServiceConnection != null) {
                unbindService(timerServiceConnection!!)
            }
            if (networkServiceConnection != null) {
                unbindService(networkServiceConnection!!)
            }
            exitProcess(0)
        }
    }

    /**
     * 开启沉浸状态栏
     */
    open fun enableImmersionBar() = false

    /**
     * 状态栏颜色
     */
    open fun statusBarColor() = android.R.color.transparent

    fun showLoading(show:Boolean, tag:String="正在加载") {
        if (show) {
            if (loadingDialog != null) {
                loadingDialog?.dismiss()
                loadingDialog = null
            }
            loadingDialog = LoadingDialog(tag)
            loadingDialog?.show(supportFragmentManager, "loading")
        }else {
            loadingDialog?.dismiss()
        }
    }

    fun setLoadingText(text:String) {
        loadingDialog?.setText(text)
    }

    protected fun showProgressDialog(show:Boolean) {
        if (show) {
            if (progressDialog != null) {
                progressDialog?.dismiss()
                progressDialog = null
            }
            progressDialog = ProgressDialog()
            progressDialog?.setMax(100)
            progressDialog?.show(supportFragmentManager, "download")
        }else {
            progressDialog?.dismiss()
        }
    }

    protected fun setProgressDialog(progress:Int) {
        progressDialog?.setProgress(progress)
    }

    /**
     * 监听usb扫码枪输入/外接键盘输入
     */
    private var eventFirst: KeyEvent? = null
    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
        if (event.keyCode != KeyEvent.KEYCODE_BACK && event.deviceId != -1) {//不拦截返回键和软键盘输入
//            if (keyboardId == 0 && scanBoxId == 0) {
//                if (scanKeyInterval == 0L) {
//                    scanKeyInterval = System.currentTimeMillis()
//                    eventFirst = event
//                }else {
//                    if (System.currentTimeMillis() - scanKeyInterval > 10) {
//                        keyboardId = event.deviceId//记录按键deviceId
//                        scanBoxId = 0
//                    }else {
//                        scanBoxId = event.deviceId
//                        keyboardId = 0
//                    }
//                }
//            }
            if (mScannerKeyEventHelper == null) {
                mScannerKeyEventHelper = ScannerKeyEventHelper(this)
            }
//            if (scanBoxId != 0) {
//                if (eventFirst != null) {
//                    mScannerKeyEventHelper?.analysisKeyEvent(eventFirst)
//                    eventFirst = null
//                }
                mScannerKeyEventHelper?.analysisKeyEvent(event)
//            }else if (keyboardId != 0) {
//                mScannerKeyEventHelper?.analysisKeyboardEvent(event)
//            }
            return true
        }
        return super.dispatchKeyEvent(event);
    }

    override fun onScanSuccess(data: String?) {
        qrCodeBack?.invoke(data?:"")
    }

    override fun onKeyValue(key: String?) {
    }

    //启动串口扫码
    private fun startSerialPortService() {
        if (serialPortServiceConnection == null) {
            serialPortServiceConnection = object:ServiceConnection{
                override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                    (service as SerialPortService.MyBinder).getService().setCallback(object:SerialPortService.CallBack{
                        override fun openBack(success: Boolean) {
                            if (!success) {
                                toast("串口打开失败，扫码不可用！")
                            }
                        }

                        override fun getCode(code: String) {
                            LogUtil.e("read qrcode=$code")
                            runOnUiThread {
                                qrCodeBack?.invoke(code)
                            }
                        }
                    })
                }

                override fun onServiceDisconnected(name: ComponentName?) {
                }
            }
            val intent = Intent(this, SerialPortService::class.java)
            bindService(intent, serialPortServiceConnection!!, BIND_AUTO_CREATE)
            startService(intent)
        }
    }

    private fun startNetworkService() {
        if (networkServiceConnection == null) {
            networkServiceConnection = object:ServiceConnection{
                override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                    (service as NetworkStatusService.MyBinder).getService().setCallback(object: NetworkStatusService.CallBack{
                        override fun getNetworkStatus(ok: Boolean) {
                            Global.networkOk = ok
                        }
                    })
                }

                override fun onServiceDisconnected(name: ComponentName?) {
                }
            }
            val intent = Intent(this, NetworkStatusService::class.java)
            bindService(intent, networkServiceConnection!!, BIND_AUTO_CREATE)
            startService(intent)
        }
    }

    private fun startSocketService() {
        if (socketServiceConnection == null) {
            socketServiceConnection = object:ServiceConnection{
                override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                    socketService = (service as SocketService.MyBinder).getService()
                    socketService?.setCallback(object:SocketService.CallBack{
                        override fun onEvent(eventType: SocketService.EventType, data: Any?) {
                            when(eventType) {
                                SocketService.EventType.CONNECT_STATION -> toast(if (data == "success") "连接服务站成功" else "连接服务站失败:$data")
                                SocketService.EventType.RECEIVE_FROM_STATION -> toast("获得服务站数据：$data")
                                SocketService.EventType.STATION_CLOSE -> toast("服务站关闭连接")
//                                SocketService.Type.SEND_GROUP -> toast("发送组播：$data")
//                                SocketService.Type.RECEIVE_GROUP -> toast("接收组播：$data")
                                SocketService.EventType.CONNECT_FROM_CLIENT -> toast("新终端接入：$data")
                                SocketService.EventType.CLIENT_CLOSE -> toast("终端关闭连接：$data")
                                SocketService.EventType.SEND_TO_STATION -> toast("终端发给服务站：$data")
                                SocketService.EventType.REQ_FROM_CLIENT -> handleClientReq(data as SocketService.ClientReq)
                            }
                        }
                    })
                }

                override fun onServiceDisconnected(name: ComponentName?) {}
            }
            val intent = Intent(this, SocketService::class.java)
            bindService(intent, socketServiceConnection!!, BIND_AUTO_CREATE)
            startService(intent)
        }
    }

    private fun startTimerService() {
        if (timerServiceConnection == null) {
            timerServiceConnection = object:ServiceConnection{
                override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                    (service as TimerService.MyBinder).getService().setCallback(object: TimerService.CallBack{
                        override fun scheduledTasks() {
                            runOnUiThread { timerBack?.invoke() }
                        }
                    })
                }

                override fun onServiceDisconnected(name: ComponentName?) {
                }
            }
            val intent = Intent(this, TimerService::class.java)
            bindService(intent, timerServiceConnection!!, BIND_AUTO_CREATE)
            startService(intent)
        }
    }

    //二维码回调
    fun getQRCode(back:(code:String)->Unit) {
        qrCodeBack = back
    }

    fun getTimer(back:()->Unit) {
        timerBack = back
    }

    fun receiveStation(back:(data:String)->Unit) {
        stationBack = back
    }

    fun isConnectStation(): Boolean {
        return socketService?.isConnectStation()?:false
    }

    fun getConnectList() : ConcurrentHashMap<String, WebSocket>? {
        return socketService?.getConnectList()
    }

    fun isConnectICBC(): Boolean {
        return socketService?.isConnectICBC()?:false
    }

    fun sendDataToAllClients(data:String) {
        socketService?.sendDataToAllClients(data)
    }

//    private fun sendHeartbeat2Station() {
//        socketService?.pushSendData("heartbeat")
//    }

    fun checkAppVersion() {
        FirUpdateUtil.checkNewVersion {
            if (it.hasNewVersion) {
//                YesOrNoDialog("发现新版本 ${it.version}", "${it.message} \n\n 立即升级?") {ok->
//                    if (ok) {
                        var pbDialog:ProgressDialog? = null
                        val apkPath = "${FirUpdateUtil.apkDir}${it.version}.apk"
                        InstallUtils.with(this)
                            .setApkUrl("${it.apkUrl}")
                            .setApkPath(apkPath)
                            .setCallBack(object: InstallUtils.DownloadCallBack{
                                override fun onStart() {
                                }

                                override fun onComplete(path: String?) {
                                    pbDialog?.dismiss()
                                    InstallUtils.installAPK(this@BaseActivity, path, null)
                                }

                                override fun onLoading(total: Long, current: Long) {
                                    if (pbDialog == null) {
                                        pbDialog = ProgressDialog(false)
                                        pbDialog?.show(supportFragmentManager, "UpgradeApp")
                                        pbDialog?.setMax(total.toInt())
                                    }
                                    pbDialog?.setProgress(current.toInt())
                                }

                                override fun onFail(e: Exception?) {
                                    pbDialog?.dismiss()
                                    toast("下载失败")
                                    start(this@BaseActivity,  MainActivity::class.java)
                                }

                                override fun cancle() {
                                    pbDialog?.dismiss()
                                    toast("下载取消")
                                    start(this@BaseActivity,  MainActivity::class.java)
                                }
                            })
                            .startDownload()
//                    }
//                }.show(supportFragmentManager, "UpgradeApp")
            }else {
                start(this@BaseActivity,  MainActivity::class.java)
            }
        }
    }

    fun configServerStation(isServer:Boolean) {
        if (isServer) {
            socketService?.stopConnectStation()
            toast("startServer")
            socketService?.startStation()
        }else {
            toast("stopServer")
            socketService?.stopStation()
        }
        ConnectUtil.groupSend()//启动时无论服务站或终端都发送一次组播，目的是(终端)获得服务站的ip或(服务站)广播ip给所有的终端
    }

    //代终端请求
    private fun handleClientReq(clientReq:SocketService.ClientReq) {
        val sp = clientReq.data.split("###")
        if (sp.size > 1) {
            val req = when(sp[0]) {
                "corp_qry" -> BaseReqBean("corp_qry", "1.0")
                "dep_qry" -> BaseReqBean("dep_qry", "1.0")
                "emp_qry" -> Global.gson.fromJson(sp[1], ReqQueryEmployInfoBean::class.java)
                "cant_qry" -> Global.gson.fromJson(sp[1], ReqQueryCanteenInfoBean::class.java)
                "meal_qry" -> Global.gson.fromJson(sp[1], ReqQueryMealInfoBean::class.java)
                "fee_qry" -> Global.gson.fromJson(sp[1], ReqQueryFeesBean::class.java)
                "face_file_qry" -> Global.gson.fromJson(sp[1], ReqQueryFaceFileBean::class.java)
//                "face_file_download" -> Global.gson.fromJson(sp[1], RspQueryFaceFileBean.FaceFile::class.java)
                "order_qry" -> Global.gson.fromJson(sp[1], ReqQueryOrderInfoBean::class.java)
                "use_consume" -> Global.gson.fromJson(sp[1], ReqUseConsumeBean::class.java)
                "pay_qry" -> Global.gson.fromJson(sp[1], ReqQueryPayDetailBean::class.java)
                "use_qry" -> Global.gson.fromJson(sp[1], ReqUseDetailBean::class.java)
                "et_use_consume" -> Global.gson.fromJson(sp[1], ReqETTicketUseConsumeBean::class.java)
                "reverse" -> Global.gson.fromJson(sp[1], ReqReverseBean::class.java)
                else -> BaseReqBean("", "")
            }
            if (req != null) {//请求响应后不要解码，直接返回给终端
                val body = ReqBean(DES3Util.EncryptData(Gson().toJson(req), Global.CorpKey), Global.CorpID)//加密请求数据
                RetrofitManager.getInstance().httpApi.post(body)?.enqueue(object :
                    Callback<ResponseBody> {
                    override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                        socketService?.sendData(clientReq.webSocket, "${Global.STATION_RSP_HEAD}${sp[0]}###${response.body()?.string()}")
                    }

                    override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
                        var errorMsg = t.message?:"请求异常"
                        when {
                            errorMsg.toLowerCase(Locale.ROOT).contains("no address associated with hostname") -> errorMsg = "请检查网络"
                            errorMsg.toLowerCase(Locale.ROOT).contains("failed to connect") -> errorMsg = "网络/服务器异常"
                            errorMsg.toLowerCase(Locale.ROOT).contains("timeout") -> errorMsg = "请求超时"
                        }
                        socketService?.sendData(clientReq.webSocket, "${Global.STATION_RSP_HEAD}${sp[0]}###errorMsg=$errorMsg")
                    }
                })
            }
        }
    }

}